import logging
import random
import re
import time

from django.contrib.auth import authenticate
from django.core.cache import cache
from django.shortcuts import render
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework_simplejwt.tokens import RefreshToken

from users.models import User
from utils.sms import RongLianSMS

logger = logging.getLogger("django")


# Create your views here.
class LoginView(APIView):
    """
    用户登录视图，处理用户通过用户名和密码进行登录的请求。

    方法:
        post(request): 接收POST请求，验证用户名和密码，并返回JWT token。

    参数:
        request (Request): 包含用户名和密码的请求对象。

    返回:
        Response: 包含登录结果、token等信息的响应对象。
    """

    def post(self, request):
        # 获取用户名和密码
        username = request.data['username']
        password = request.data['password']

        # 检查用户名或密码是否为空
        if not all([username, password]):
            return Response({
                "code": 0,
                "message": "用户名或密码不能为空"
            })

        # 验证用户凭据
        user = authenticate(username=username, password=password)

        # 如果验证失败，返回错误信息
        if not user:
            return Response({
                "code": 0,
                "message": "用户名或密码错误"
            })

        # 生成JWT token
        refresh = RefreshToken.for_user(user)

        # 返回登录成功及token信息
        return Response({
            "code": 1,
            "message": "登录成功",
            "data": {
                "token": str(refresh.access_token),
                "refresh": str(refresh),
                "user_id": user.id,
                "username": user.username
            }
        })


class SendSmsCodeView(APIView):
    """
    发送短信验证码视图，用于向已注册手机号发送6位数字验证码。

    方法:
        post(request): 接收POST请求，校验手机号并发送验证码。

    参数:
        request (Request): 包含手机号的请求对象。

    返回:
        Response: 包含发送结果的响应对象。
    """

    def post(self, request):
        try:
            # 获取手机号
            mobile = request.data["mobile"]

            # 检测类型
            type = request.data.get("type", "login")

            # 检查手机号是否为空
            if not mobile:
                return Response({
                    "code": 0,
                    "message": "手机号码不能为空"
                })

            # 校验手机号格式是否正确
            if not re.match(r"^1[3-9]\d{9}$", mobile):
                return Response({
                    "code": 0,
                    "message": "手机号码格式不正确"
                })

            # 判断手机号是否已经注册
            if type == "login":
                if not User.objects.filter(phone=mobile).exists():
                    return Response({
                        "code": 0,
                        "message": "手机号码未注册"
                    })
            elif type == "register":
                if User.objects.filter(phone=mobile).exists():
                    return Response({
                        "code": 0,
                        "message": "手机号码已注册"
                    })

            # 使用缓存控制短信发送频率（60秒内只能发一次）
            last_sms_time_key = f"users:login:send_sms_code:{mobile}"
            last_sms_time = cache.get(last_sms_time_key)

            now = time.time()

            if last_sms_time and now - last_sms_time < 60:
                remaining_time = 60 - (now - last_sms_time)
                return Response({
                    "code": 0,
                    "message": f"请{remaining_time}秒后重试"
                })

            # 生成4随机验证码
            sms_code = "".join(random.choices("0123456789", k=4))

            # 将验证码存入缓存，有效期5分钟
            sms_code_key = f"users:login:sms_code:{sms_code}"
            cache.set(sms_code_key, sms_code, timeout=60 * 5)
            logger.info(f"验证码: {sms_code}")

            rl_sms = RongLianSMS()
            rl_sms.send_sms(mobile, sms_code, 5)
            # 记录本次发送时间，防止频繁发送
            cache.set(last_sms_time_key, now, timeout=60)

            # 返回发送成功响应
            return Response({
                "code": 1,
                "message": "发送成功",
                "sms_code": sms_code
            })
        except Exception as e:
            # 异常处理：返回发送失败信息
            return Response({
                "code": 0,
                "message": f"发送失败: {str(e)}"
            })


class RegisterView(APIView):
    def post(self, request):
        mobile = request.data.get("mobile")
        sms_code = request.data.get("sms_code")

        if not all([mobile, sms_code]):
            return Response({
                "code": 0,
                "message": "手机号或验证码不能为空"
            })

        # 校验手机号格式是否正确
        if not re.match(r"^1[3-9]\d{9}$", mobile):
            return Response({
                "code": 0,
                "message": "手机号码格式不正确"
            })

        # 从缓存中获取验证码
        sms_code_key = f"users:login:sms_code:{sms_code}"
        cache_sms_code = cache.get(sms_code_key)

        if not cache_sms_code:
            return Response({
                "code": 0,
                "message": "验证码已过期"
            })

        if cache_sms_code != sms_code:
            return Response({
                "code": 0,
                "message": "验证码错误"
            })

        user = User.objects.get(phone=mobile)
        refresh = RefreshToken.for_user(user)
        cache.delete(sms_code_key)

        return Response({
            "code": 1,
            "message": "登录成功",
            "data": {
                "token": str(refresh.access_token),
                "refresh": str(refresh),
                "user_id": user.id,
                "username": user.username
            }
        })


class UserRegisterView(APIView):
    def post(self, request):
        try:
            username = request.data.get("username")
            password = request.data.get("password")
            mobile = request.data.get("mobile")
            sms_code = request.data.get("code")

            if not all([username, password, mobile, sms_code]):
                return Response({
                    "code": 0,
                    "message": "用户名、密码、手机号或验证码不能为空"
                })

            if not re.match(r"^1[3-9]\d{9}$", mobile):
                return Response({
                    "code": 0,
                    "message": "手机号码格式不正确"
                })

            if len(password) < 6:
                return Response({
                    "code": 0,
                    "message": "密码长度不能小于6位"
                })

            if len(password) > 16:
                return Response({
                    "code": 0,
                    "message": "密码长度不能大于16位"
                })

            if not re.search(r'[0-9]', password) or not re.search(r'[a-zA-Z]', password):
                logger.warning(f"用户注册失败：密码必须包含数字和字母，用户名: {username}")
                return Response({
                    "code": 0,
                    "errmsg": "密码必须包含数字和字母"
                })

            if User.objects.filter(phone=mobile).exists():
                return Response({
                    "code": 0,
                    "message": "手机号码已注册"
                })

            # 从缓存中获取验证码
            sms_code_key = f"users:login:sms_code:{sms_code}"
            cache_sms_code = cache.get(sms_code_key)

            if not cache_sms_code:
                return Response({
                    "code": 0,
                    "message": "验证码已过期"
                })

            if cache_sms_code != sms_code:
                return Response({
                    "code": 0,
                    "message": "验证码错误"
                })

            user = User.objects.create_user(username=username, password=password, phone=mobile)
            logger.info(f"新用户注册成功: {user.username}")

            cache.delete(sms_code_key)

            refresh = RefreshToken.for_user(user)

            return Response({
                "code": 1,
                "message": "注册成功",
                "data": {
                    "token": str(refresh.access_token),
                    "refresh": str(refresh),
                    "user_id": user.id,
                    "username": user.username
                }
            })
        except Exception as e:
            return Response({
                "code": 0,
                "message": f"注册失败: {str(e)}"
            })
